<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!--[if lt IE 9]>
  <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<![endif]-->
<title>VIM 中文用户手册: 小窍门</title>
<link rel="stylesheet" href="vim-stylesheet.css" type="text/css" />
<link rel="canonical" href="https://yianwillis.github.io/vimcdoc/doc/usr_12.html" />
<script type="text/javascript" src="vimcdoc.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<nav id=banner>
<form action=tags.html target="tag_iframe">
  <input type="text" name="tag" id="tag" placeholder="标签搜索">
</form>
<iframe name="tag_iframe" src=""></iframe>
<a href="help.html">帮助总览</a> &middot;
<hr/>
<a href="quickref.html">快速参考</a> &middot;
<a href="index.html">命令索引</a> &middot;
<a href="eval.html#functions">函数列表</a> &middot;
<a href="quickref.html#option-list">选项列表</a> &middot;
<hr/>
<a href="usr_toc.html">用户手册</a> &middot;
<a href="help.html#reference_toc">参考手册</a> &middot;
</nav>

<header>
<h2>usr_12</h2>
</header>
<article id=outer>
<section class=inner>
<b class="vimtag"> <a name="usr_12.txt">usr_12.txt</a> </b>    适用于 Vim 9.0 版本。   最近更新: 2022年8月

                     <code class="vim">VIM 用户手册 - by Bram Moolenaar</code>
                                <code class="vim">译者</code>: Nek_in

                                小窍门


通过组合一些命令，你可以用 Vim 完成几乎所有的工作。本章将介绍一些有用的命令组
合。涉及的命令大都是前面章节介绍过的，但也会有一点新命令。

 <a href="usr_12.html#12.1">12.1</a>   单词替换
 <a href="usr_12.html#12.2">12.2</a>   把 "Last, First" 改成 "First Last"
 <a href="usr_12.html#12.3">12.3</a>   排序
 <a href="usr_12.html#12.4">12.4</a>   反转行顺序
 <a href="usr_12.html#12.5">12.5</a>   单词统计
 <a href="usr_12.html#12.6">12.6</a>   查阅 man 信息
 <a href="usr_12.html#12.7">12.7</a>   删除多余空格
 <a href="usr_12.html#12.8">12.8</a>   查找单词的使用位置

        下一章:  <a href="usr_20.html#usr_20.txt">usr_20.txt</a>   快速键入命令行命令
        前一章:  <a href="usr_11.html#usr_11.txt">usr_11.txt</a>   从崩溃中恢复
          目录:  <a href="usr_toc.html#usr_toc.txt">usr_toc.txt</a> 

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="12.1">12.1</a> </b>  单词替换</h4>
替换命令可以在全文中用一个单词替换另一个单词:

<code class="example">        :%s/four/4/g</code>
<code class="example"></code>
"%" 范围前缀表示在所有行中执行替换。最后的 "g" 标记表示替换行中的所有匹配点。
    如果你有一个像 "thirtyfour" 这样的单词，上面的命令会出错。这种情况下，这
个单词会被替换成 "thirty4"。要解决这个问题，用 "\&lt;" 来指定匹配单词开头:

<code class="example">        :%s/\&lt;four/4/g</code>
<code class="example"></code>
显然，这样在处理 "fourteen" 的时候还是会出错。用 "\&gt;" 来解决这个问题:

<code class="example">        :%s/\&lt;four\&gt;/4/g</code>
<code class="example"></code>
如果你在编码，你可能只想替换注释中的 "four"，而保留代码中的。由于这很难指定，
可以在替换命令中加一个 "c" 标记，这样，Vim 会在每次替换前提示你:

<code class="example">        :%s/\&lt;four\&gt;/4/gc</code>
<code class="example"></code>
<code class="example"></code>
在 多 个 文 件 中 替 换

假设你需要替换多个文件中的单词。你的一个选择是打开每一个文件并手工修改。但是
使用记录和回放命令会快很多。
    假设你有一个包括有 C++ 文件的目录，所有的文件都以 ".cpp" 结尾。有一个叫
"GetResp" 的函数，你需要把它改名为 "GetAnswer"。

        vim *.cpp               启动 Vim，用当前目录的所有 C++ 文件作为文件参
                                数。启动后你会停在第一个文件上。
        qq                      用 q 作为寄存器启动一次记录。
        :%s/\&lt;GetResp\&gt;/GetAnswer/g
                                在第一个文件中执行替换。
        :wnext                  保存文件并移到下一个文件。
        q                       中止记录。
        @q                      回放 q 中的记录。这会执行又一次替换和
                                ":wnext"。你现在可以检查一下记录有没有错。
        999@q                   对剩下的文件执行 q 中的命令

Vim 会在最后一个文件上报错，因为 ":wnext" 无法移到下一个文件上。这时所有的文件
中的操作都完成了。

        <code class="note">备注</code>:
        在回放记录的时候，任何错误都会中止回放的过程。所以，要<code class="note">注意</code>保证记录中
        的命令不会产生错误。

这里有一个陷阱: 如果有一个文件不包含 "GetResp"，Vim 会报错，而整个过程会中止，
要避免这个问题，可以在替换命令后面加一个标记:

<code class="example">        :%s/\&lt;GetResp\&gt;/GetAnswer/ge</code>
<code class="example"></code>
"e" 标记通知 ":substitute" 命令找不到不是错误。

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="12.2">12.2</a> </b>  把 "Last, First" 改成 "First Last"</h4>
你有如下样式的一个名字列表:

<code class="section">        Doe, John </code>
<code class="section">        Smith, Peter </code>

你想把它改成:

<code class="section">        John Doe </code>
<code class="section">        Peter Smith </code>

这可以用一个命令完成:

<code class="example">        :%s/\([^,]*\), \(.*\)/\2 \1/</code>
<code class="example"></code>
我们把这个命令分解成几个部分。首先，很明显它是一个替换命令。"%" 是行范围，表示
作用于全文。这样替换命令会作用于全文的每一行。
    替换命令的参数格式是 "from/to"，正斜杠区分 "from" 模式和 "to" 字符串。所
以，"from" 部分是:
<code class="section">                                                        \([^,]*\), \(.*\) </code>

        第一对 \( 和 \) 之间的部分匹配 "Last"           \(     \)
            匹配除逗号外的任何东西                        [^,]
            任意多次                                          *
        匹配逗号空格 ", "                                        ,
        第二对 \( 和 \) 之间的部分匹配 "First"                     \(  \)
            匹配任意字符                                             .
            任意多次                                                  *

在 "to" 部分，我们有 "\2" 和 "\1"。这些称为 "反向引用"。它们指向前面模式中的
\( 和 \) 间的部分。"\2" 指向模式中的第二对 \( 和 \) 间的部分，也就是 "First"
名 (<code class="vim">译者注</code>: 英文中 Last Name 表示姓，即家族名，后面的 First Name 表示名字)。
"\1" 指向第一对 \( \)，即 "Last" 名。
    你可以在替换部分使用多达 9 个反向引用。"\0" 表示整个匹配部分。还有一些特殊
的项可以用在替换命令中。请参阅  <a href="change.html#sub-replace-special">sub-replace-special</a> 。

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="12.3">12.3</a> </b>  排序</h4>
在你的 Makefile 中常常会有文件列表。例如:

<code class="section">        OBJS = \ </code>
<code class="section">                version.o \ </code>
<code class="section">                pch.o \ </code>
<code class="section">                getopt.o \ </code>
<code class="section">                util.o \ </code>
<code class="section">                getopt1.o \ </code>
<code class="section">                inp.o \ </code>
<code class="section">                patch.o \ </code>
<code class="section">                backup.o </code>

要对这个文件列表排序可以用一个外部过滤命令:

<code class="example">        /^OBJS</code>
<code class="example">        j</code>
<code class="example">        :.,/^$/-1!sort</code>
<code class="example"></code>
这会先移到 "OBJS" 开头的行，向下移动一行，然后一行行执行过滤，直到遇到一个空
行。你也可以先选中所有需要排序的行，然后执行 "!sort"。那更容易一些，但如果有很
多行就比较麻烦。
    上面操作的结果将是:

<code class="section">        OBJS = \ </code>
<code class="section">                backup.o </code>
<code class="section">                getopt.o \ </code>
<code class="section">                getopt1.o \ </code>
<code class="section">                inp.o \ </code>
<code class="section">                patch.o \ </code>
<code class="section">                pch.o \ </code>
<code class="section">                util.o \ </code>
<code class="section">                version.o \ </code>


<code class="note">注意</code>，列表中每一行都有一个续行符，但排序后就错掉了！"backup.o" 在列表的最后，
不需要续行符，但排序后它被移动了。这时它需要有一个续行符。
    最简单的解决方案是用 "A \<code class="special">&lt;Esc&gt;</code>" 补一个续行符。你也可以在最后一行放一个续行
符，由于后面有一个空行，这样做是不会有问题的。

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="12.4">12.4</a> </b>  反转行顺序</h4>
 <a href="repeat.html#:global">:global</a>  命令可以和  <a href="change.html#:move">:move</a>  命令联用，将所有行移动到文件首部。结果是文件被按
行反转了次序。命令是: 
<code class="example"></code>
<code class="example">        :global/^/move 0</code>
<code class="example"></code>
缩写: 
<code class="example"></code>
<code class="example">        :g/^/m 0</code>
<code class="example"></code>
正则表达式 "^" 匹配行首 (即使该行是一个空行)。 <a href="change.html#:move">:move</a>  命令将匹配的行移动到那个
想像中的第 0 行之后。这样匹配的行就成了文件中的第一行。由于  <a href="repeat.html#:global">:global</a>  命令不会
被改变了的行号搞混，该命令继续匹配文件中剩余的行并将它们一一变为首行。

这对一个行范围同样有效。先移动到第一行上方并做标记 't' (mt)。然后移动到范围的
最后一行并键入: 
<code class="example"></code>
<code class="example">        :'t+1,.g/^/m 't</code>
<code class="example"></code>
</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="12.5">12.5</a> </b>  单词统计</h4>
有时你要写一些有最高字数限制的文字。Vim 可以帮你计算字数。
    如果你需要统计的是整个文件的字数，可以用这个命令:

<code class="example">        g CTRL-G</code>
<code class="example"></code>
不要在 "g" 后面输入一个空格，这里只是方便阅读。
    它的输出是:

<code class="section">        Col 1 of 0; Line 141 of 157; Word 748 of 774; Byte 4489 of 4976 </code>

        (<code class="vim">译者注</code>: 中文是:
<code class="section">        第 1/0 列; 第 141/157 行; 第 748/774 个词; 第 4489/4976 个字节 </code>
        )

你可以看到你在第几个单词 (748) 上以及文件中的单词总数 (774)。

如果你要知道的是全文的一部分的字数，你可以移到该文本的开头，输入 "g <code class="keystroke">CTRL-G</code>"，
然后移到该段文字的末尾，再输入 "g <code class="keystroke">CTRL-G</code>"，最后心算出结果来。这是一种很好的心
算练习，不过不是那么容易。比较方便的办法是使用可视模式，选中你要计算字数的文
本，然后输入 "g <code class="keystroke">CTRL-G</code>"，结果将是:

<code class="section">        Selected 5 of 293 Lines; 70 of 1884 Words; 359 of 10928 Bytes </code>

        (<code class="vim">译者注</code>: 中文是:
<code class="section">        选择了 5/293 行; 70/1884 个词; 359/10928 个字节 </code>
        )


要知道其它计算字数，行数和其它东西总数的方法，可以参见  <a href="tips.html#count-items">count-items</a> 。

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="12.6">12.6</a> </b>  查阅 man 信息                                   <b class="vimtag"> <a name="find-manpage">find-manpage</a> </b></h4>
编辑一个脚本文件或者 C 程序的时候，有时你会需要从 man 手册中查询某个命令或者函
数的用法 (使用 Unix 的情况下)。让我们先用一个简单的方法: 把鼠标移到对应的单词
上然后输入:

<code class="example">        K</code>
<code class="example"></code>
Vim 会在对应的单词上执行外部命令: man。如果能找到相应的手册，那个手册页就会被
显示出来。它常常用 more 一类的程序显示页面。在手册滚动到文件末并回车，控制就会
回到 Vim 中。

这种方法的缺点是你不能同时查看手册和编辑文档。这里有一种办法可以把手册显示到一
个 Vim 的窗口中。首先，加载 man 文件类型的外挂:

<code class="example">        :runtime! ftplugin/man.vim</code>
<code class="example"></code>
如果你经常用到这种方法，可以把这个命令加到你的 vimrc 文件中。现在你可以用
":Man" 命令打开一个显示 man 手册的窗口了:

<code class="example">        :Man csh</code>
<code class="example"></code>
你可以在这个新的窗口中上下滚动，而手册的本文会用语法高亮的形式显示。这样，你可
以找到需要的地方，并用 <code class="keystroke">CTRL-W</code> w 跳转到原来的窗口中继续工作。
    要指定手册的章节，可以在手册名称前面指定。例如，要找第三章的 "echo":

<code class="example">        :Man 3 echo</code>
<code class="example"></code>
要跳转到另一个由 "word(1)" 形式定义的手册，只要在上面敲 <code class="keystroke">CTRL-]</code>。无论怎样，
":Man" 命令总使用同一个窗口。

要显示当前光标下的单词的手册，这样:

<code class="example">        \K</code>
<code class="example"></code>
(如果你重定义了 <code class="special">&lt;Leader&gt;</code>，用那个字符代替上面命令的反斜杠)。
例如，你想知道下面语句中的 "strstr()" 函数的返回值:

<code class="section">        if ( strstr(input, "aap") == ) </code>

可以把光标移到 "strstr" 并输入 "\K"。手册使用的窗口会显示 strstr() 的信息。

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="12.7">12.7</a> </b>  删除多余的空格</h4>
有些人认为行末的空格是无用，浪费而难看的。要删除这些每行后面多余的空格，可以执
行如下命令:

<code class="example">        :%s/\s\+$//</code>
<code class="example"></code>
命令前面指明范围是 "%"，所以这会作用于整个文件。"substitute" 命令的匹配模式是
"\s\+$"。这表示行末 ($) 前的一个或者多个 (\+) 空格 (\s)。后面我们会介绍怎样写
这样的模式。见  <a href="usr_27.html#usr_27.txt">usr_27.txt</a> 。
    替换命令的 "to" 部分是空的: "//"。这样就会删除那些匹配的空白字符。

另一种没有用的空格是 Tab 前面的字符。通常这可以删除而不影响格式。但并不是总这
样！所以，你最好手工删除它。执行如下命令:

<code class="example">        /       </code>
<code class="example"></code>
你什么都看不见，其实这是一个空格加一个 TAB 键。相当于 "/<code class="special">&lt;Space&gt;</code><code class="special">&lt;Tab&gt;</code>"。现在，
你可以用 "x" 删除多余的空格，并保证格式没有改变。接着你可以用 "n" 找到下一个位
置并重复这个操作。

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="12.8">12.8</a> </b>  查找单词的使用位置</h4>
如果你是一个 UNIX 用户，你可以用 Vim 和 grep 命令的组合来完成编辑包括特定单词
的所有文件的工作。这在你编辑一个程序而且想查看和编辑看所有的包括使用某个变量
的文件的时候非常有用。
    举个例子，假设想编辑所有包括单词 "frame_counter" 的 C 源文件，你可以执行如
下命令:

<code class="example">        vim `grep -l frame_counter *.c`</code>
<code class="example"></code>
让我们分析一下这个命令。grep 从一组文件中查找特定的单词。由于指定了 -l 参数，
grep 只列出文件而不打印匹配点。被查找的单词是 "frame_counter"，其实这可以是任
何正则表达式。(<code class="note">注意</code>: grep 所使用的正则表达式与 Vim 使用的不完全一样)。
    整个命令用反引号 (`) 包起来，这告诉 UNIX 的外壳使用该命令的输出作为命令行
的一部分。于是，grep 命令产生一个文件列表，并作为 Vim 的命令参数。Vim 将编辑
grep 列出来的所有文件。你可以通过 ":next" 和 ":first" 命令一个一个处理这些文
件。


找 到 每 一 行

上面的命令只是找到包括单词的那个文件。你还需要知道单词在该文件中出现的地方。
    Vim 有一个内置的命令用于在一组文件中找一个指定的字符串。例如，如果你想在所
有的 C 文件中查找 "error_string"，可以使用如下命令:

<code class="example">        :grep error_string *.c</code>
<code class="example"></code>
这会使 Vim 在所有指定的文件 (*.c) 中查找 "error_string"。Vim 会打开第一个匹配
的文件并将光标定位在第一个匹配行。要到下一个匹配行 (无论在哪个文件)，可以执行
"cnext" 命令。要回到上一个匹配行，可以用 ":cprev" 命令。使用 "clist" 可以看到
所有的匹配点。
    ":grep" 命令会使用一个外部的程序。可能是 grep (在 Unix 上) 或者 findstr
(在 Windows 上)。你可以通过 <a href="options.html#'grepprg'">'grepprg'</a> 选项修改这个设置。

</section><hr class="doubleline" /><section class=inner>
<h4></h4>下一章:   <a href="usr_20.html#usr_20.txt">usr_20.txt</a>   快速键入命令行命令

版权: 参见  <a href="usr_01.html#manual-copyright">manual-copyright</a>   vim:tw=78:ts=8:noet:ft=help:norl:
</section>
</article>
<footer>
Generated by vim2html
</footer>
</body>
</html>
